use libp2p::{
    autonat, identify,
    identity::Keypair,
    kad,
    request_response::{self, ProtocolSupport},
    swarm::NetworkBehaviour,
    PeerId, StreamProtocol,
};
use rand::rngs::OsRng;
use std::time::Duration;

use crate::p2p::{
    constant::common::{IDENTIFY_PROTOCOL, STREAM_PROTOCOL},
    mode::file_share::{FileRequest, FileResponse},
};

#[derive(NetworkBehaviour)]
pub struct Behaviour {
    pub autonat: autonat::v2::client::Behaviour,
    pub identify: identify::Behaviour,
    pub request_response: request_response::cbor::Behaviour<FileRequest, FileResponse>,
    pub kademlia: kad::Behaviour<kad::store::MemoryStore>,
}

impl Behaviour {
    pub fn new(key: &Keypair, peer_id: PeerId, probe_interval: u64) -> Self {
        Self {
            autonat: autonat::v2::client::Behaviour::new(
                OsRng,
                autonat::v2::client::Config::default()
                    .with_probe_interval(Duration::from_secs(probe_interval)),
            ),
            identify: identify::Behaviour::new(identify::Config::new(
                IDENTIFY_PROTOCOL.into(),
                key.public(),
            )),
            kademlia: kad::Behaviour::new(
                peer_id,
                kad::store::MemoryStore::new(key.public().to_peer_id()),
            ),
            request_response: request_response::cbor::Behaviour::new(
                [(
                    StreamProtocol::new(STREAM_PROTOCOL.into()),
                    ProtocolSupport::Full,
                )],
                request_response::Config::default(),
            ),
        }
    }
}
